

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "XMen_sm2.h"
#include "XMen_sm3.h"
#include "XMen_asn1.h"

/**
 * @brief Verify SM2 signature
 * @param buf Input message buffer to verify
 * @param buf_length Length of input message
 * @param Private_Key Private key bytes
 * @param Publickey Public key bytes (x||y coordinates)
 * @param sig Signature bytes to verify
 * @param siglen Length of signature
 * @return 0 on success, 1 on failure
 */
int sm2verify_main(
    uint8_t* buf,
    uint32_t buf_length,
    uint8_t* Private_Key,
    uint8_t* Publickey,
    uint8_t* sig,
    uint32_t siglen)
{
    int ret = 1;
    uint8_t i;
    char* id = SM2_DEFAULT_ID;

    SM2_KEY key;
    SM2_SIGN_CTX verify_ctx;

    int vr;
    // Copy key bytes into SM2_KEY structure
    for (i = 0; i < 32u; i++)
    {
        key.private_key[i] = Private_Key[i];
        key.public_key.x[i] = Publickey[i];
        key.public_key.y[i] = Publickey[i + 32];
    }

    // Initialize verification context
    if (XMen_lib_sm2_verify_init(&verify_ctx, &key, id, strlen(id)) != 1)
    {
    }

    // Update verification context with message
    if (XMen_lib_sm2_verify_update(&verify_ctx, buf, buf_length) != 1)
    {
    }

    // Complete verification
    if ((vr = XMen_lib_sm2_verify_finish(&verify_ctx, sig, siglen)) < 0)
    {
    }

    // Return 0 if verification succeeded
    if (vr == 1)
    {
        ret = 0;
    }

    return ret;
}

/**
 * @brief Generate SM2 signature
 * @param buf Input message buffer to sign
 * @param buf_length Length of input message
 * @param Private_Key Private key bytes
 * @param Publickey Public key bytes (x||y coordinates)
 * @param Sig_Result Output buffer for signature
 * @param siglen Output length of signature
 * @return E_OK on success, E_NOK on failure
 */
Std_ReturnType sm2sign_main(
    uint8_t* buf,
    uint32_t buf_length,
    uint8_t* Private_Key,
    uint8_t* Publickey,
    uint8_t* Sig_Result,
    uint32_t* siglen)
{
    Std_ReturnType ret = E_OK;
    char* id = SM2_DEFAULT_ID;
    SM2_KEY key;
    uint32_t len;

    SM2_SIGN_CTX sign_ctx;
    uint8_t i = 0;
    len = buf_length;

    // Copy key bytes into SM2_KEY structure
    for (i = 0; i < 32; i++)
    {
        key.private_key[i] = Private_Key[i];
        key.public_key.x[i] = Publickey[i];
        key.public_key.y[i] = Publickey[i + 32];
    }

    // Initialize signing context
    ret = XMen_lib_sm2_sign_init(&sign_ctx, &key, id, strlen(id));
    if (ret == E_OK)
    {
        // Update signing context with message
        ret = XMen_lib_sm2_sign_update(&sign_ctx, buf, len);
    }

    if (ret == E_OK)
    {
        // Complete signing and output signature
        ret = XMen_lib_sm2_sign_finish(&sign_ctx, Sig_Result, siglen);
    }

    return ret;
}

/**
 * @brief Generate SM2 signature with private key
 * @param key SM2 key pair containing private key
 * @param dgst Message digest to sign (32 bytes)
 * @param sig Output signature structure
 * @return 1 on success, -1 on failure
 */
int XMen_lib_sm2_do_sign(const SM2_KEY* key, const uint8_t dgst[32], SM2_SIGNATURE* sig)
{
    SM2_JACOBIAN_POINT P1;
    SM2_JACOBIAN_POINT* P = &P1;
    SM2_BN d;        // Private key
    SM2_BN d_inv;    // Inverse of private key + 1
    SM2_BN e;        // Message digest
    SM2_BN k;        // Random number
    SM2_BN x;        // x-coordinate
    SM2_BN t;        // Temporary value
    SM2_BN r;        // Signature r component
    SM2_BN s;        // Signature s component
    uint8_t Bn_Zero_dowhile[2] = { 0 };

    // Convert private key from bytes
    XMen_lib_sm2_bn_from_bytes(d, key->private_key);

    // Calculate (private key + 1)^-1 mod n
    XMen_lib_sm2_fn_add(d_inv, d, SM2_ONE);
    if (XMen_lib_sm2_bn_is_zero(d_inv))
    {
        return -1;
    }
    XMen_lib_sm2_fn_inv(d_inv, d_inv);

    // Convert message digest from bytes
    XMen_lib_sm2_bn_from_bytes(e, dgst);
    do
    {
        Bn_Zero_dowhile[0] = 0;
        Bn_Zero_dowhile[1] = 0;

        // Generate random k until valid
        do
        {
            if (XMen_lib_sm2_fn_rand(k) != 1)
            {
                return -1;
            }
        } while (XMen_lib_sm2_bn_is_zero(k));

        // Calculate k*G
        XMen_lib_sm2_jacobian_point_mul_generator(P, k);
        XMen_lib_sm2_jacobian_point_get_xy(P, x, NULL);

        // Reduce e and x mod n if needed
        if (XMen_lib_sm2_bn_cmp(e, SM2_N) >= 0)
        {
            XMen_lib_sm2_bn_sub(e, e, SM2_N);
        }
        if (XMen_lib_sm2_bn_cmp(x, SM2_N) >= 0)
        {
            XMen_lib_sm2_bn_sub(x, x, SM2_N);
        }

        // Calculate r = (e + x) mod n
        XMen_lib_sm2_fn_add(r, e, x);

        // Check if r + k = n
        XMen_lib_sm2_bn_add(t, r, k);
        if (XMen_lib_sm2_bn_is_zero(r) || XMen_lib_sm2_bn_cmp(t, SM2_N) == 0)
        {
            Bn_Zero_dowhile[0] = 1;
        }

        if (Bn_Zero_dowhile[0] != 1)
        {
            // Calculate s = ((1 + d)^-1 * (k - r*d)) mod n
            XMen_lib_sm2_fn_mul(t, r, d);                 
            XMen_lib_sm2_fn_sub(k, k, t);                 
            XMen_lib_sm2_fn_mul(s, d_inv, k);
        }

        // Check if s is zero
        if (XMen_lib_sm2_bn_is_zero(s))
        {
            Bn_Zero_dowhile[1] = 1;
        }
    } while ((Bn_Zero_dowhile[0] != 0) || (Bn_Zero_dowhile[1] != 0));

    // Convert signature components to bytes
    XMen_lib_sm2_bn_to_bytes(r, sig->r);     
    XMen_lib_sm2_bn_to_bytes(s, sig->s);
    return 1;
}

/**
 * @brief Verify SM2 signature
 * @param key SM2 key pair containing public key
 * @param dgst Message digest to verify (32 bytes)
 * @param sig Signature structure to verify
 * @return 1 if signature is valid, -1 if invalid
 */
int XMen_lib_sm2_do_verify(const SM2_KEY* key, const uint8_t dgst[32], const SM2_SIGNATURE* sig)
{
    SM2_JACOBIAN_POINT P1;
    SM2_JACOBIAN_POINT* P = &P1;
    SM2_JACOBIAN_POINT R1;
    SM2_JACOBIAN_POINT* R = &R1;
    SM2_BN r;        // Signature r component
    SM2_BN s;        // Signature s component
    SM2_BN e;        // Message digest
    SM2_BN x;        // x-coordinate
    SM2_BN t;        // Temporary value

    // Convert public key to Jacobian point
    XMen_lib_sm2_jacobian_point_from_bytes(P, (const uint8_t*)&key->public_key);

    // Convert signature components from bytes
    XMen_lib_sm2_bn_from_bytes(r, sig->r);     
    XMen_lib_sm2_bn_from_bytes(s, sig->s);

    // Verify signature components are in valid range
    if (XMen_lib_sm2_bn_is_zero(r) == 1 || XMen_lib_sm2_bn_cmp(r, SM2_N) >= 0 || XMen_lib_sm2_bn_is_zero(s) == 1 || XMen_lib_sm2_bn_cmp(s, SM2_N) >= 0)
    {
        return -1;
    }

    // Convert message digest from bytes
    XMen_lib_sm2_bn_from_bytes(e, dgst);

    // Calculate t = r + s mod n
    XMen_lib_sm2_fn_add(t, r, s);     
    if (XMen_lib_sm2_bn_is_zero(t))
    {
        return -1;
    }

    // Calculate R = s*G + t*P
    XMen_lib_sm2_jacobian_point_mul_sum(R, t, P, s);
    XMen_lib_sm2_jacobian_point_get_xy(R, x, NULL);

    // Reduce e and x mod n if needed
    if (XMen_lib_sm2_bn_cmp(e, SM2_N) >= 0)
    {
        XMen_lib_sm2_bn_sub(e, e, SM2_N);
    }
    if (XMen_lib_sm2_bn_cmp(x, SM2_N) >= 0)
    {
        XMen_lib_sm2_bn_sub(x, x, SM2_N);
    }

    // Calculate e + x mod n and compare with r
    XMen_lib_sm2_fn_add(e, e, x);
    if (XMen_lib_sm2_bn_cmp(e, r) != 0)
    {
        return -1;
    }
    return 1;
}

/**
 * @brief Convert SM2 signature to DER encoding
 * @param sig Input signature structure
 * @param out Output buffer for DER encoding
 * @param outlen Output length of DER encoding
 * @return 1 on success, -1 on failure
 */
int XMen_lib_sm2_signature_to_der(const SM2_SIGNATURE* sig, uint8_t** out, uint32_t* outlen)
{
    uint32_t len = 0;
    if (!sig)
    {
        return 0;
    }

    // Calculate total length and encode signature components
    if (XMen_lib_asn1_sm2_integer_to_der(sig->r, 32, NULL, &len) != 1 || XMen_lib_asn1_sm2_integer_to_der(sig->s, 32, NULL, &len) != 1
        || XMen_lib_asn1_sm2_sequence_header_to_der(len, out, outlen) != 1 || XMen_lib_asn1_sm2_integer_to_der(sig->r, 32, out, outlen) != 1
        || XMen_lib_asn1_sm2_integer_to_der(sig->s, 32, out, outlen) != 1)
    {
        return -1;
    }
    return 1;
}

/**
 * @brief Parse SM2 signature from DER encoding
 * @param sig Output signature structure
 * @param in Input DER encoded signature
 * @param inlen Input length
 * @return 1 on success, -1 on failure
 */
int XMen_lib_sm2_signature_from_der(SM2_SIGNATURE* sig, const uint8_t** in, uint32_t* inlen)
{
    int ret;
    const uint8_t* d;
    uint32_t dlen;
    const uint8_t* r;
    uint32_t rlen;
    const uint8_t* s;
    uint32_t slen;

    // Parse sequence header
    if ((ret = XMen_lib_asn1_sm2_sequence_from_der(&d, &dlen, in, inlen)) != 1)
    {
        if (ret < 0)
            return ret;
    }

    // Parse signature components
    if (XMen_lib_asn1_sm2_integer_from_der(&r, &rlen, &d, &dlen) != 1 || XMen_lib_asn1_sm2_integer_from_der(&s, &slen, &d, &dlen) != 1
        || XMen_lib_asn1_sm2_length_le(rlen, 32) != 1 || XMen_lib_asn1_sm2_length_le(slen, 32) != 1 || XMen_lib_asn1_sm2_length_is_zero(dlen) != 1)
    {
        return -1;
    }

    // Copy signature components to output structure
    memset(sig, 0, sizeof(*sig));
    memcpy(sig->r + 32 - rlen, r, rlen);
    memcpy(sig->s + 32 - slen, s, slen);
    return 1;
}

// Global signature structure for testing
SM2_SIGNATURE Sign_Test;

/**
 * @brief Generate SM2 signature in DER format
 * @param key SM2 key pair
 * @param dgst Message digest to sign (32 bytes)
 * @param sigbuf Output buffer for DER signature
 * @param siglen Output length of DER signature
 * @return 1 on success, -1 on failure
 */
int XMen_lib_sm2_sign(const SM2_KEY* key, const uint8_t dgst[32], uint8_t* sigbuf, uint32_t* siglen)
{
    if (!key || !dgst || !sigbuf || !siglen)
    {
        return -1;
    }

    // Generate signature
    if (XMen_lib_sm2_do_sign(key, dgst, &Sign_Test) != 1)
    {
        return -1;
    }

    // Convert to DER format
    *siglen = 0;
    if (XMen_lib_sm2_signature_to_der(&Sign_Test, &sigbuf, siglen) != 1)
    {
        return -1;
    }

    // Print signature components for debugging
    printf("Sign R\n");
    for (int i = 0; i < 32; i++)
    {
        printf("%02x ", Sign_Test.r[i]);
    }
    printf("\n");
    printf("Sign S\n");
    for (int i = 0; i < 32; i++)
    {
        printf("%02x ", Sign_Test.s[i]);
    }
    printf("\n");
    return 1;
}

/**
 * @brief Generate SM2 signature with fixed length DER encoding
 * @param key SM2 key pair
 * @param dgst Message digest to sign (32 bytes)
 * @param siglen Required length of DER signature
 * @param sig Output buffer for DER signature
 * @return 1 on success, -1 on failure
 */
int XMen_lib_sm2_sign_fixlen(const SM2_KEY* key, const uint8_t dgst[32], uint32_t siglen, uint8_t* sig)
{
    unsigned int trys = 200;
    uint8_t buf[SM2_MAX_SIGNATURE_SIZE];
    uint32_t len;

    // Verify requested signature length is valid
    switch (siglen)
    {
    case SM2_signature_compact_size:
    case SM2_signature_typical_size:
    case SM2_signature_max_size:
        break;
    default:
        return -1;
    }

    // Try generating signatures until we get one of the desired length
    while (trys--)
    {
        if (XMen_lib_sm2_sign(key, dgst, buf, &len) != 1)
        {
            return -1;
        }
        if (len == siglen)
        {
            memcpy(sig, buf, len);
            return 1;
        }
    }

    return -1;
}

/**
 * @brief Verify SM2 signature in DER format
 * @param key SM2 key pair
 * @param dgst Message digest to verify (32 bytes)
 * @param sigbuf DER encoded signature
 * @param siglen Length of DER signature
 * @return 1 if signature is valid, -1 if invalid
 */
int XMen_lib_sm2_verify(const SM2_KEY* key, const uint8_t dgst[32], const uint8_t* sigbuf, uint32_t siglen)
{
    SM2_SIGNATURE sig;

    if (!key || !dgst || !sigbuf || !siglen)
    {
        return -1;
    }

    // Parse DER signature
    if (XMen_lib_sm2_signature_from_der(&sig, &sigbuf, &siglen) != 1 || XMen_lib_asn1_sm2_length_is_zero(siglen) != 1)
    {
        return -1;
    }

    // Verify signature
    if (XMen_lib_sm2_do_verify(key, dgst, &sig) != 1)
    {
        return -1;
    }
    return 1;
}

/**
 * @brief Compute SM2 Z value (hash of user ID and public key)
 * @param z Output Z value (32 bytes)
 * @param pub Public key point
 * @param id User ID string
 * @param idlen Length of user ID
 * @return 1 on success, -1 on failure
 */
int XMen_lib_sm2_compute_z(uint8_t z[32], const SM2_POINT* pub, const char* id, uint32_t idlen)
{
    LIB_SM3_CTX ctx;
    uint8_t z_init[210] = {
        0x00u, 0x80u, 0x31u, 0x32u, 0x33u, 0x34u, 0x35u, 0x36u, 0x37u, 0x38u, 0x31u, 0x32u, 0x33u, 0x34u, 0x35u, 0x36u, 0x37u,
        0x38u, 0xFFu, 0xFFu, 0xFFu, 0xFEu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
        0xFFu, 0xFFu, 0xFFu, 0xFFu, 0x00u, 0x00u, 0x00u, 0x00u, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFCu, 0x28u,
        0xE9u, 0xFAu, 0x9Eu, 0x9Du, 0x9Fu, 0x5Eu, 0x34u, 0x4Du, 0x5Au, 0x9Eu, 0x4Bu, 0xCFu, 0x65u, 0x09u, 0xA7u, 0xF3u, 0x97u,
        0x89u, 0xF5u, 0x15u, 0xABu, 0x8Fu, 0x92u, 0xDDu, 0xBCu, 0xBDu, 0x41u, 0x4Du, 0x94u, 0x0Eu, 0x93u, 0x32u, 0xC4u, 0xAEu,
        0x2Cu, 0x1Fu, 0x19u, 0x81u, 0x19u, 0x5Fu, 0x99u, 0x04u, 0x46u, 0x6Au, 0x39u, 0xC9u, 0x94u, 0x8Fu, 0xE3u, 0x0Bu, 0xBFu,
        0xF2u, 0x66u, 0x0Bu, 0xE1u, 0x71u, 0x5Au, 0x45u, 0x89u, 0x33u, 0x4Cu, 0x74u, 0xC7u, 0xBCu, 0x37u, 0x36u, 0xA2u, 0xF4u,
        0xF6u, 0x77u, 0x9Cu, 0x59u, 0xBDu, 0xCEu, 0xE3u, 0x6Bu, 0x69u, 0x21u, 0x53u, 0xD0u, 0xA9u, 0x87u, 0x7Cu, 0xC6u, 0x2Au,
        0x47u, 0x40u, 0x02u, 0xDFu, 0x32u, 0xE5u, 0x21u, 0x39u, 0xF0u, 0xA0u,
    };

    if (!z || !pub || !id)
    {
        return -1;
    }

    // Copy public key coordinates into Z initialization data
    memcpy(&z_init[18 + 32 * 4], pub->x, 32);
    memcpy(&z_init[18 + 32 * 5], pub->y, 32);

    // Initialize hash context
    XMen_lib_sm3_init(&ctx);

    // Handle default ID differently
    if (strcmp(id, SM2_DEFAULT_ID) == 0)
    {
        XMen_lib_sm3_update(&ctx, z_init, sizeof(z_init));
    }
    else
    {
        // Add ID length bits
        uint8_t idbits[2];
        idbits[0] = (uint8_t)(idlen >> 5);
        idbits[1] = (uint8_t)(idlen << 3);
        XMen_lib_sm3_update(&ctx, idbits, 2);

        // Add ID and curve parameters
        XMen_lib_sm3_update(&ctx, (uint8_t*)id, idlen);
        XMen_lib_sm3_update(&ctx, z_init + 18, 32 * 6);
    }

    // Finalize hash
    XMen_lib_sm3_finish(&ctx, z);
    return 1;
}

/**
 * @brief Initialize SM2 signing context
 * @param ctx Signing context to initialize
 * @param key SM2 key pair
 * @param id User ID string
 * @param idlen Length of user ID
 * @return E_OK on success, E_NOK on failure
 */
Std_ReturnType XMen_lib_sm2_sign_init(SM2_SIGN_CTX* ctx, const SM2_KEY* key, const char* id, uint32_t idlen)
{
    if (!ctx || !key)
    {
        return E_NOK;
    }

    // Copy key and initialize hash context
    ctx->key = *key;
    XMen_lib_sm3_init(&ctx->lib_sm3_ctx);

    // Add Z value to hash if ID provided
    if (id)
    {
        uint8_t z[LIB_SM3_DIGEST_SIZE];
        if (idlen <= 0 || idlen > SM2_MAX_ID_LENGTH)
        {
            return E_NOK;
        }
        XMen_lib_sm2_compute_z(z, &key->public_key, id, idlen);
        XMen_lib_sm3_update(&ctx->lib_sm3_ctx, z, sizeof(z));
    }
    return E_OK;
}

/**
 * @brief Update SM2 signing context with message data
 * @param ctx Signing context
 * @param data Message data to add
 * @param datalen Length of message data
 * @return E_OK on success, E_NOK on failure
 */
Std_ReturnType XMen_lib_sm2_sign_update(SM2_SIGN_CTX* ctx, const uint8_t* data, uint32_t datalen)
{
    if (!ctx)
    {
        return E_NOK;
    }
    if (data && datalen > 0)
    {
        XMen_lib_sm3_update(&ctx->lib_sm3_ctx, data, datalen);
    }
    return E_OK;
}

/**
 * @brief Finalize SM2 signature generation
 * @param ctx Signing context
 * @param sig Output buffer for signature
 * @param siglen Output length of signature
 * @return E_OK on success, E_NOK on failure
 */
Std_ReturnType XMen_lib_sm2_sign_finish(SM2_SIGN_CTX* ctx, uint8_t* sig, uint32_t* siglen)
{
    uint8_t dgst[LIB_SM3_DIGEST_SIZE];

    if (!ctx || !sig || !siglen)
    {
        return E_NOK;
    }

    // Finalize message hash
    XMen_lib_sm3_finish(&ctx->lib_sm3_ctx, dgst);

    // Print digest for debugging
    printf("dgst\n");
    for (int i = 0; i < 32; i++)
    {
        printf("%02x ", dgst[i]);
    }
    printf("\n");

    // Generate signature
    if (XMen_lib_sm2_sign(&ctx->key, dgst, sig, siglen) != 1)
    {
        return E_NOK;
    }
    return E_OK;
}
/**
 * @brief Finalize SM2 signature generation with fixed length
 * @param ctx Signing context
 * @param siglen Required length of signature
 * @param sig Output buffer for signature
 * @return 1 on success, -1 on failure
 */
int XMen_lib_sm2_sign_finish_fixlen(SM2_SIGN_CTX* ctx, uint32_t siglen, uint8_t* sig)
{
    uint8_t dgst[LIB_SM3_DIGEST_SIZE];

    if (!ctx || !sig || !siglen)
    {
        return -1;
    }

    // Finalize message hash
    XMen_lib_sm3_finish(&ctx->lib_sm3_ctx, dgst);

    // Generate fixed length signature
    if (XMen_lib_sm2_sign_fixlen(&ctx->key, dgst, siglen, sig) != 1)
    {
        return -1;
    }
    return 1;
}


/**
 * @brief Initialize SM2 signature verification context
 * @param ctx Verification context
 * @param key Public key for verification
 * @param id Optional ID for Z value computation
 * @param idlen Length of ID
 * @return 1 on success, -1 on failure
 */
int XMen_lib_sm2_verify_init(SM2_SIGN_CTX* ctx, const SM2_KEY* key, const char* id, uint32_t idlen)
{
    // Check input parameters
    if (!ctx || !key)
    {
        return -1;
    }

    // Initialize context
    memset(ctx, 0, sizeof(*ctx));
    ctx->key.public_key = key->public_key;
    XMen_lib_sm3_init(&ctx->lib_sm3_ctx);

    // If ID is provided, compute Z value and update hash
    if (id)
    {
        uint8_t z[LIB_SM3_DIGEST_SIZE];
        if (idlen <= 0 || idlen > SM2_MAX_ID_LENGTH)
        {
            return -1;
        }
        XMen_lib_sm2_compute_z(z, &key->public_key, id, idlen);
        XMen_lib_sm3_update(&ctx->lib_sm3_ctx, z, sizeof(z));
    }
    return 1;
}

/**
 * @brief Update SM2 signature verification with message data
 * @param ctx Verification context
 * @param data Message data to verify
 * @param datalen Length of message data
 * @return 1 on success, -1 on failure
 */
int XMen_lib_sm2_verify_update(SM2_SIGN_CTX* ctx, const uint8_t* data, uint32_t datalen)
{
    // Check context
    if (!ctx)
    {
        return -1;
    }

    // Update hash with message data if provided
    if (data && datalen > 0)
    {
        XMen_lib_sm3_update(&ctx->lib_sm3_ctx, data, datalen);
    }
    return 1;
}

/**
 * @brief Finalize SM2 signature verification
 * @param ctx Verification context
 * @param sig Signature to verify
 * @param siglen Length of signature
 * @return 1 if signature is valid, -1 if invalid
 */
int XMen_lib_sm2_verify_finish(SM2_SIGN_CTX* ctx, const uint8_t* sig, uint32_t siglen)
{
    uint8_t dgst[LIB_SM3_DIGEST_SIZE];

    // Check input parameters
    if (!ctx || !sig)
    {
        return -1;
    }

    // Finalize message hash
    XMen_lib_sm3_finish(&ctx->lib_sm3_ctx, dgst);

    // Verify signature
    if (XMen_lib_sm2_verify(&ctx->key, dgst, sig, siglen) != 1)
    {
        return -1;
    }
    return 1;
}

/**
 * @brief Key derivation function based on SM3
 * @param in Input data
 * @param inlen Length of input
 * @param outlen Desired output length
 * @param out Output buffer
 * @return 1 on success
 */
int XMen_lib_sm2_kdf(const uint8_t* in, uint32_t inlen, uint32_t outlen, uint8_t* out)
{
    LIB_SM3_CTX ctx;
    uint8_t counter_be[4];
    uint8_t dgst[LIB_SM3_DIGEST_SIZE];
    uint32_t counter = 1;
    uint32_t len;

    // Generate key material in chunks
    while (outlen)
    {
        // Convert counter to big-endian
        PUTU32(counter_be, counter);
        counter++;

        // Hash input data with counter
        XMen_lib_sm3_init(&ctx);
        XMen_lib_sm3_update(&ctx, in, inlen);
        XMen_lib_sm3_update(&ctx, counter_be, sizeof(counter_be));
        XMen_lib_sm3_finish(&ctx, dgst);

        // Copy hash output to result
        len = outlen < LIB_SM3_DIGEST_SIZE ? outlen : LIB_SM3_DIGEST_SIZE;
        memcpy(out, dgst, len);
        out += len;
        outlen -= len;
    }

    // Clear sensitive data
    memset(&ctx, 0, sizeof(LIB_SM3_CTX));
    memset(dgst, 0, sizeof(dgst));
    return 1;
}

/**
 * @brief Check if buffer contains all zeros
 * @param buf Buffer to check
 * @param len Length of buffer
 * @return 1 if all zeros, 0 otherwise
 */
static int all_zero(const uint8_t* buf, uint32_t len)
{
    uint32_t i;
    for (i = 0; i < len; i++)
    {
        if (buf[i])
        {
            return 0;
        }
    }
    return 1;
}

/**
 * @brief Perform SM2 encryption operation
 * @param key Public key for encryption
 * @param in Input plaintext buffer
 * @param inlen Length of input plaintext
 * @param out Output ciphertext structure
 * @return 1 on success, -1 on failure
 */
int XMen_lib_sm2_do_encrypt(const SM2_KEY* key, const uint8_t* in, uint32_t inlen, SM2_CIPHERTEXT* out)
{
    // Temporary variables for computation
    SM2_BN k;
    SM2_JACOBIAN_POINT P1, *P = &P1;
    SM2_JACOBIAN_POINT _C1, *C1 = &_C1;
    SM2_JACOBIAN_POINT _kP, *kP = &_kP;
    uint8_t x2y2[64];
    LIB_SM3_CTX lib_sm3_ctx;

    // Validate input length
    if (!(SM2_MIN_PLAINTEXT_SIZE <= inlen && inlen <= SM2_MAX_PLAINTEXT_SIZE))
    {
        return -1;
    }

    // Convert public key to Jacobian point
    XMen_lib_sm2_jacobian_point_from_bytes(P, (uint8_t*)&key->public_key);

retry:
    // Generate random k value
    do
    {
        if (XMen_lib_sm2_fn_rand(k) != 1)
        {
            return -1;
        }
    } while (XMen_lib_sm2_bn_is_zero(k));

    // Calculate C1 = [k]G
    XMen_lib_sm2_jacobian_point_mul_generator(C1, k);
    XMen_lib_sm2_jacobian_point_to_bytes(C1, (uint8_t*)&out->point);

    // Calculate [k]PB
    XMen_lib_sm2_jacobian_point_mul(kP, k, P);
    XMen_lib_sm2_jacobian_point_to_bytes(kP, x2y2);

    // Generate key using KDF
    XMen_lib_sm2_kdf(x2y2, 64, inlen, out->ciphertext);

    // Check if KDF output is all zeros
    if (all_zero(out->ciphertext, inlen))
    {
        goto retry;
    }

    // Calculate C2 = M 鈯� t
    XMen_lib_sm2_memxor(out->ciphertext, out->ciphertext, in, inlen);
    out->ciphertext_size = (uint32_t)inlen;

    // Calculate C3 = Hash(x2 || M || y2)
    XMen_lib_sm3_init(&lib_sm3_ctx);
    XMen_lib_sm3_update(&lib_sm3_ctx, x2y2, 32);
    XMen_lib_sm3_update(&lib_sm3_ctx, in, inlen);
    XMen_lib_sm3_update(&lib_sm3_ctx, x2y2 + 32, 32);
    XMen_lib_sm3_finish(&lib_sm3_ctx, out->hash);

    // Clear sensitive data
    secure_clear(k, sizeof(k));
    secure_clear(kP, sizeof(SM2_JACOBIAN_POINT));
    secure_clear(x2y2, sizeof(x2y2));

    return 1;
}

/**
 * @brief Perform SM2 encryption with fixed point size
 * @param key Public key for encryption
 * @param in Input plaintext buffer
 * @param inlen Length of input plaintext
 * @param point_size Required size of point encoding
 * @param out Output ciphertext structure
 * @return 1 on success, -1 on failure
 */
int XMen_lib_sm2_do_encrypt_fixlen(const SM2_KEY* key, const uint8_t* in, uint32_t inlen, int point_size, SM2_CIPHERTEXT* out)
{
    unsigned int trys = 200;
    SM2_BN k;
    SM2_JACOBIAN_POINT P1;
    SM2_JACOBIAN_POINT* P = &P1;
    SM2_JACOBIAN_POINT _C1, * C1 = &_C1;
    SM2_JACOBIAN_POINT _kP, * kP = &_kP;
    uint8_t x2y2[64];
    LIB_SM3_CTX lib_sm3_ctx;

    // Validate input length
    if (!(SM2_MIN_PLAINTEXT_SIZE <= inlen && inlen <= SM2_MAX_PLAINTEXT_SIZE))
    {
        return -1;
    }

    // Validate point size
    switch (point_size)
    {
    case SM2_ciphertext_compact_point_size:
    case SM2_ciphertext_typical_point_size:
    case SM2_ciphertext_max_point_size:
        break;
    default:
        return -1;
    }

    // Convert public key to Jacobian point
    XMen_lib_sm2_jacobian_point_from_bytes(P, (uint8_t*)&key->public_key);

retry:
    // Generate random k value
    do
    {
        if (XMen_lib_sm2_fn_rand(k) != 1)
        {
            return -1;
        }
    } while (XMen_lib_sm2_bn_is_zero(k));
    
    // Calculate C1 = [k]G
    XMen_lib_sm2_jacobian_point_mul_generator(C1, k);
    XMen_lib_sm2_jacobian_point_to_bytes(C1, (uint8_t*)&out->point);

    // Check if point encoding matches required size
    if (trys)
    {
        uint32_t len = 0;
        XMen_lib_asn1_sm2_integer_to_der(out->point.x, 32, NULL, &len);
        XMen_lib_asn1_sm2_integer_to_der(out->point.y, 32, NULL, &len);
        if (len != (uint32_t)point_size)
        {
            trys--;
            goto retry;
        }
    }
    else
    {
        secure_clear(k, sizeof(k));
        return -1;
    }

    // Calculate [k]PB
    XMen_lib_sm2_jacobian_point_mul(kP, k, P);
    XMen_lib_sm2_jacobian_point_to_bytes(kP, x2y2);

    // Generate key using KDF
    XMen_lib_sm2_kdf(x2y2, 64, inlen, out->ciphertext);

    // Check if KDF output is all zeros
    if (all_zero(out->ciphertext, inlen))
    {
        goto retry;
    }

    // Calculate C2 = M 鈯� t
    XMen_lib_sm2_memxor(out->ciphertext, out->ciphertext, in, inlen);
    out->ciphertext_size = (uint32_t)inlen;

    // Calculate C3 = Hash(x2 || M || y2)
    XMen_lib_sm3_init(&lib_sm3_ctx);
    XMen_lib_sm3_update(&lib_sm3_ctx, x2y2, 32);
    XMen_lib_sm3_update(&lib_sm3_ctx, in, inlen);
    XMen_lib_sm3_update(&lib_sm3_ctx, x2y2 + 32, 32);
    XMen_lib_sm3_finish(&lib_sm3_ctx, out->hash);

    // Clear sensitive data
    secure_clear(k, sizeof(k));
    secure_clear(kP, sizeof(SM2_JACOBIAN_POINT));
    secure_clear(x2y2, sizeof(x2y2));
    return 1;
}

/**
 * @brief Perform SM2 decryption operation
 * @param key Private key for decryption
 * @param in Input ciphertext structure
 * @param out Output plaintext buffer
 * @param outlen Length of output plaintext
 * @return 1 on success, -1 on failure
 */
int XMen_lib_sm2_do_decrypt(const SM2_KEY* key, const SM2_CIPHERTEXT* in, uint8_t* out, uint32_t* outlen)
{
    int ret = -1;
    SM2_BN d;
    SM2_JACOBIAN_POINT _C1, *C1 = &_C1;
    uint8_t x2y2[64];
    LIB_SM3_CTX lib_sm3_ctx;
    uint8_t hash[32];

    // Convert C1 to point and verify it's on curve
    XMen_lib_sm2_jacobian_point_from_bytes(C1, (uint8_t*)&in->point);
    if (!XMen_lib_sm2_jacobian_point_is_on_curve(C1))
    {
        return -1;
    }

    // Convert private key to big number
    XMen_lib_sm2_bn_from_bytes(d, key->private_key);
    
    // Calculate [d]C1
    XMen_lib_sm2_jacobian_point_mul(C1, d, C1);

    // Get coordinates
    XMen_lib_sm2_jacobian_point_to_bytes(C1, x2y2);
    
    // Generate key using KDF
    XMen_lib_sm2_kdf(x2y2, 64, in->ciphertext_size, out);
    if (all_zero(out, in->ciphertext_size))
    {
        goto end;
    }

    // Recover plaintext M = C2 鈯� t
    XMen_lib_sm2_memxor(out, out, in->ciphertext, in->ciphertext_size);
    *outlen = in->ciphertext_size;

    // Verify hash C3 = Hash(x2 || M || y2)
    XMen_lib_sm3_init(&lib_sm3_ctx);
    XMen_lib_sm3_update(&lib_sm3_ctx, x2y2, 32);
    XMen_lib_sm3_update(&lib_sm3_ctx, out, in->ciphertext_size);
    XMen_lib_sm3_update(&lib_sm3_ctx, x2y2 + 32, 32);
    XMen_lib_sm3_finish(&lib_sm3_ctx, hash);
    
    ret = memcmp(in->hash, hash, sizeof(hash));
    if (ret != 0)
    {
        goto end;
    }
    ret = 1;

end:
    // Clear sensitive data
    secure_clear(d, sizeof(d));
    secure_clear(C1, sizeof(SM2_JACOBIAN_POINT));
    secure_clear(x2y2, sizeof(x2y2));
    return ret;
}
/**
 * @brief Convert SM2 ciphertext to DER encoding
 * @param C Input ciphertext structure
 * @param out Output DER buffer (can be NULL for length calculation)
 * @param outlen Output length of DER encoding
 * @return 1 on success, -1 on failure, 0 on invalid input
 */
int XMen_lib_sm2_ciphertext_to_der(const SM2_CIPHERTEXT* C, uint8_t** out, uint32_t* outlen)
{
    uint32_t len = 0;
    if (!C)
    {
        return 0;
    }
    
    if (XMen_lib_asn1_sm2_integer_to_der(C->point.x, 32, NULL, &len) != 1 || XMen_lib_asn1_sm2_integer_to_der(C->point.y, 32, NULL, &len) != 1
        || XMen_lib_asn1_sm2_octet_string_to_der(C->hash, 32, NULL, &len) != 1
        || XMen_lib_asn1_sm2_octet_string_to_der(C->ciphertext, C->ciphertext_size, NULL, &len) != 1
        || XMen_lib_asn1_sm2_sequence_header_to_der(len, out, outlen) != 1 
        || XMen_lib_asn1_sm2_integer_to_der(C->point.x, 32, out, outlen) != 1
        || XMen_lib_asn1_sm2_integer_to_der(C->point.y, 32, out, outlen) != 1
        || XMen_lib_asn1_sm2_octet_string_to_der(C->hash, 32, out, outlen) != 1
        || XMen_lib_asn1_sm2_octet_string_to_der(C->ciphertext, C->ciphertext_size, out, outlen) != 1)
    {
        return -1;
    }
    return 1;
}

/**
 * @brief Parse SM2 ciphertext from DER encoding
 * @param C Output ciphertext structure
 * @param in Input DER buffer
 * @param inlen Input length of DER data
 * @return 1 on success, -1 on failure
 */
int XMen_lib_sm2_ciphertext_from_der(SM2_CIPHERTEXT* C, const uint8_t** in, uint32_t* inlen)
{
    int ret;
    const uint8_t* d;
    uint32_t dlen;
    const uint8_t* x;
    const uint8_t* y; 
    const uint8_t* hash;
    const uint8_t* c;
    uint32_t xlen, ylen, hashlen, clen;

    ret = XMen_lib_asn1_sm2_sequence_from_der(&d, &dlen, in, inlen);
    if (ret < 0)
        return ret;

    if (XMen_lib_asn1_sm2_integer_from_der(&x, &xlen, &d, &dlen) != 1 || XMen_lib_asn1_sm2_length_le(xlen, 32) != 1)
    {
        return -1;
    }
    if (XMen_lib_asn1_sm2_integer_from_der(&y, &ylen, &d, &dlen) != 1 || XMen_lib_asn1_sm2_length_le(ylen, 32) != 1)
    {
        return -1;
    }
    if (XMen_lib_asn1_sm2_octet_string_from_der(&hash, &hashlen, &d, &dlen) != 1 || XMen_lib_asn1_sm2_check(hashlen == 32) != 1)
    {
        return -1;
    }
    if (XMen_lib_asn1_sm2_octet_string_from_der(&c, &clen, &d, &dlen) != 1
        || XMen_lib_asn1_sm2_length_le(clen, SM2_MAX_PLAINTEXT_SIZE) != 1)
    {
        return -1;
    }
    ret = XMen_lib_asn1_sm2_length_is_zero(dlen);
    if (ret != 1)
    {
        return -1;
    }
    memset(C, 0, sizeof(SM2_CIPHERTEXT));
    memcpy(C->point.x + 32 - xlen, x, xlen);
    memcpy(C->point.y + 32 - ylen, y, ylen);
    if (XMen_lib_sm2_point_is_on_curve(&C->point) != 1)
    {
        return -1;
    }
    memcpy(C->hash, hash, hashlen);
    memcpy(C->ciphertext, c, clen);
    C->ciphertext_size = (uint8_t)clen;
    return 1;
}

/**
 * @brief Encrypt data using SM2 public key encryption
 * @param key Public key for encryption
 * @param in Input plaintext buffer
 * @param inlen Length of input plaintext
 * @param out Output buffer for ciphertext
 * @param outlen Output length of ciphertext
 * @return 1 on success, -1 on failure
 */
int XMen_lib_sm2_encrypt(const uint8_t* key, const uint8_t* in, uint32_t inlen, uint8_t* out, uint32_t* outlen)
{
    SM2_CIPHERTEXT C;
    SM2_KEY k;

    for (uint8_t i = 0; i < 32; i++)
    {
        k.public_key.x[i] = key[i];
        k.public_key.y[i] = key[i + 32];
    }


    if ( !in || !out || !outlen)
    {
        return -1;
    }
    if (!inlen)
    {
        return -1;
    }

    if (XMen_lib_sm2_do_encrypt(&k, in, inlen, &C) != 1)
    {
        return -1;
    }
    *outlen = 0;
    
    if (XMen_lib_sm2_ciphertext_to_der(&C, &out, outlen) != 1)
    {
        return -1;
    }
    return 0;
}

/**
 * @brief Encrypt data using SM2 with fixed point size
 * @param key Public key for encryption
 * @param in Input plaintext buffer
 * @param inlen Length of input plaintext
 * @param point_size Size of point encoding
 * @param out Output buffer for ciphertext
 * @param outlen Output length of ciphertext
 * @return 1 on success, -1 on failure
 */
int XMen_lib_sm2_encrypt_fixlen(
    const SM2_KEY* key,
    const uint8_t* in,
    uint32_t inlen,
    int point_size,
    uint8_t* out,
    uint32_t* outlen)
{
    SM2_CIPHERTEXT C;

    if (!key || !in || !out || !outlen)
    {
        return -1;
    }
    if (!inlen)
    {
        return -1;
    }

    if (XMen_lib_sm2_do_encrypt_fixlen(key, in, inlen, point_size, &C) != 1)
    {
        return -1;
    }
    *outlen = 0;
    
    if (XMen_lib_sm2_ciphertext_to_der(&C, &out, outlen) != 1)
    {
        return -1;
    }
    return 1;
}

/**
 * @brief Decrypt data using SM2 private key
 * @param key Private key for decryption
 * @param in Input ciphertext buffer
 * @param inlen Length of input ciphertext
 * @param out Output buffer for plaintext
 * @param outlen Output length of plaintext
 * @return 1 on success, -1 on failure
 */
int XMen_lib_sm2_decrypt(const uint8_t* key, const uint8_t* in, uint32_t inlen, uint8_t* out, uint32_t* outlen)
{
    SM2_CIPHERTEXT C;
       SM2_KEY k;

    for (uint8_t i = 0; i < 32; i++)
    {
        k.private_key[i] = key[i];
    }

    if (!in || !out || !outlen)
    {
        return -1;
    }
    
    if (XMen_lib_sm2_ciphertext_from_der(&C, &in, &inlen) != 1 || XMen_lib_asn1_sm2_length_is_zero(inlen) != 1)
    {
        return -1;
    }
    
    if (XMen_lib_sm2_do_decrypt(&k, &C, out, outlen) != 1)
    {
        return -1;
    }
    return 0;
}

/**
 * @brief Perform ECDH key agreement using SM2
 * @param key Local private key
 * @param peer_public Peer's public key point
 * @param out Output shared secret point
 * @return 1 on success, -1 on failure
 */
int XMen_lib_sm2_do_ecdh(const SM2_KEY* key, const SM2_POINT* peer_public, SM2_POINT* out)
{
    if (XMen_lib_sm2_point_mul(out, key->private_key, peer_public) != 1)
    {
        return -1;
    }
    return 1;
}

/**
 * @brief Perform ECDH key agreement with encoded public key
 * @param key Local private key
 * @param peer_public Peer's encoded public key
 * @param peer_public_len Length of peer's public key
 * @param out Output shared secret point
 * @return 1 on success, -1 on failure
 */
int XMen_lib_sm2_ecdh(const SM2_KEY* key, const uint8_t* peer_public, uint32_t peer_public_len, SM2_POINT* out)
{
    SM2_POINT point;

    if (!key || !peer_public || !peer_public_len || !out)
    {
        return -1;
    }
    
    if (XMen_lib_sm2_point_from_octets(&point, peer_public, peer_public_len) != 1)
    {
        return -1;
    }
    
    if (XMen_lib_sm2_do_ecdh(key, &point, out) != 1)
    {
        return -1;
    }
    return 1;
}

/**
 * @brief Generate SM2 signature using optimized algorithm
 * @param d Private key value
 * @param dgst Message digest to sign
 * @param sig Output signature structure
 * @return 1 on success, -1 on failure
 */
int XMen_lib_sm2_do_sign_fast(const SM2_Fn d, const uint8_t dgst[32], SM2_SIGNATURE* sig)
{
    SM2_JACOBIAN_POINT R;
    SM2_BN e;
    SM2_BN k;
    SM2_BN x1;
    SM2_BN r;
    SM2_BN s;

    // Convert message digest to integer e
    XMen_lib_sm2_bn_from_bytes(e, dgst);
    if (XMen_lib_sm2_bn_cmp(e, SM2_N) >= 0)
    {
        XMen_lib_sm2_bn_sub(e, e, SM2_N);
    }

    do
    {
        // Generate random k value
        if (XMen_lib_sm2_fn_rand(k) != 1)
        {
            return -1;
        }
    } while (XMen_lib_sm2_bn_is_zero(k));

    // Calculate R = [k]G
    XMen_lib_sm2_jacobian_point_mul_generator(&R, k);
    
    // Get x-coordinate of R
    XMen_lib_sm2_jacobian_point_get_xy(&R, x1, NULL);

    // Calculate r = (e + x1) mod n
    XMen_lib_sm2_fn_add(r, e, x1);

    // Calculate s = ((k + r) * d - r) mod n
    XMen_lib_sm2_bn_add(s, k, r);
    XMen_lib_sm2_fn_mul(s, s, d);
    XMen_lib_sm2_fn_sub(s, s, r);

    // Convert signature components to bytes
    XMen_lib_sm2_bn_to_bytes(r, sig->r);
    XMen_lib_sm2_bn_to_bytes(s, sig->s);
    return 1;
}

void func_data1(void)
{
    uint8_t ret = E_NOT_OK;
    char* sm2_userid = SM2_DEFAULT_ID;
    // 测试输入数据
    uint8_t inputdata[] = {0x7C, 0x93, 0xAA, 0x2C, 0xB2, 0x89, 0xD3, 0x63, 0x94, 0x53, 0xCE, 0x12, 0x40, 0x8F, 0x81, 0x29, 0x53, 0x33, 0x52, 0x8D, 0x04, 0x81, 0x16, 0x3C, 0x76, 0xC9, 0x2C, 0x2E, 0xD5, 0xA2, 0x8F, 0x48, 0x46, 0xE6, 0x3B, 0xC4, 0x6A, 0x17, 0xAD, 0x1F, 0x89, 0x4D, 0x48, 0xF7, 0x1A, 0xDD, 0x66, 0x1C, 0x00, 0x52, 0x9B, 0x96, 0x1C, 0x6D, 0x86, 0xE7, 0xB4, 0xB0, 0xE6, 0x02, 0x46, 0xF0, 0xD8, 0x14, 0x10, 0x07, 0x62, 0xAC, 0xA1, 0x5F, 0x89, 0xC7, 0x81, 0x26, 0xC5, 0x4A, 0xC7, 0xCB, 0xF7, 0x42, 0x39, 0x1B, 0x65, 0xC7, 0x0C, 0x9D, 0x82, 0x7E, 0xB9, 0x9C, 0x33, 0xAE, 0x14, 0xF6, 0xD2, 0x66, 0x0A, 0x80, 0xD3, 0xCD, 0xB3, 0x72, 0xD1, 0x42, 0xD4, 0xC9, 0xFD, 0x15, 0x8D, 0x77, 0x22, 0xF8, 0x1C, 0x74, 0x41, 0x21, 0x3A, 0xF3, 0x15, 0x9C, 0x53, 0x41, 0x7D, 0x10, 0x69, 0x2F, 0xD6, 0x04, 0x3A, 0x79, 0x2C, 0xA6, 0x6C, 0xBD, 0x01, 0x4A, 0xE0, 0xCE, 0xC7, 0x69, 0x18, 0xF7, 0x74, 0xF4, 0xEB, 0xA7, 0x50, 0xD6, 0x8F, 0x88, 0xD5, 0x41, 0x3D, 0x54, 0xAE, 0x08, 0xC9, 0xB1, 0xA8, 0xF7, 0xD7, 0xA6, 0x1B, 0x9C, 0x59, 0xE1, 0x63, 0xA1, 0x4D, 0x9B, 0xF9, 0x9F, 0x47, 0x20, 0x13, 0xC2, 0xE6, 0xE2, 0xE7, 0x6F, 0xD8, 0x85, 0xB6, 0x82, 0xB1, 0x35, 0xD9, 0x0F, 0x2F, 0x49, 0x45, 0xE9, 0x94, 0x89, 0xAA, 0x80, 0x7F, 0xDD, 0x8D, 0x24, 0x74, 0x5B, 0x26, 0x23, 0xC2, 0x53, 0xBF, 0x55, 0xC3, 0xDE, 0x6A, 0x91, 0xA6, 0x12, 0xA5, 0x97, 0x90, 0x90, 0xEF, 0x7D, 0x80, 0x4D, 0x04, 0x51, 0xEA, 0x5A, 0x2B, 0x1F, 0x23, 0xA3, 0xE9, 0x72, 0x04, 0x24, 0x6F, 0xB3, 0xFE, 0xFE, 0xCB, 0xF1, 0xBC, 0xEF, 0xA4, 0x2F, 0x44, 0x7D, 0xA2, 0x63, 0x28, 0x9C, 0x84, 0x85, 0x6A, 0x3E, 0xD5, 0xDC, 0xBE, 0xBB, 0xEA, 0x1C, 0x9F, 0xF9, 0x86, 0xC0, 0xB4, 0x45, 0x08, 0xEB, 0x8B, 0x04, 0x30, 0x9F, 0x72, 0x28, 0xA8, 0xBE, 0x63, 0xD3, 0x21, 0x2D, 0xAA, 0x17, 0xC7, 0xE8, 0xE2, 0xEE, 0x76, 0x44, 0xC5, 0xF3, 0x1B, 0x7A, 0xCD, 0x7A, 0xF4, 0xE9, 0x8C, 0x03, 0xBA, 0xB7, 0x54, 0xB7, 0xCC, 0x74, 0x26, 0x41, 0xBB, 0xA7, 0x3E, 0x39, 0x7D, 0x3B, 0x82, 0x8B, 0x1C, 0xA2, 0x0C, 0x74, 0x97, 0x27, 0xBD, 0x3B, 0xDC, 0x45, 0xAC, 0xEE, 0xC1, 0x8B, 0x82, 0xD4, 0x76, 0xAA, 0x27, 0xED, 0x36, 0xA6, 0x12, 0x95, 0xAD, 0x91, 0x4E, 0x0A, 0x69, 0xED, 0x24, 0x72, 0x6F, 0xDF, 0x2D, 0xF6, 0x3A, 0x1D, 0x7E, 0xA8, 0x99, 0x75, 0x58, 0xCA, 0x9D, 0xD9, 0xC4, 0x4E, 0x15, 0xF1, 0xF4, 0x0B, 0x50, 0x61, 0xA2, 0x9F, 0xA7, 0xE4, 0x3B, 0xD8, 0x7F, 0x47, 0x06, 0x9D, 0x42, 0x06, 0x75, 0xC8, 0x4B, 0x8C, 0xA5, 0x03, 0x7C, 0x20, 0xBA, 0x17, 0x59, 0xCC, 0x3F, 0x82, 0x24, 0x39, 0x2B, 0x3B, 0xF5, 0x86, 0xBB, 0x42, 0x9A, 0x38, 0x83, 0x0C, 0xB8, 0x19, 0x15, 0x50, 0x31, 0x2A, 0xDB, 0xBF, 0x12, 0xB1, 0x8F, 0x53, 0x7D, 0x3F, 0xC5, 0xF4, 0x0E, 0xF6, 0xF4, 0xD7, 0x2A, 0x2F, 0x42, 0x45, 0xAE, 0x3F, 0x30, 0xF2, 0x65, 0x4E, 0xB4, 0xC5, 0xC6, 0x8F, 0x52, 0x76, 0x12, 0xD9, 0x76, 0xD9, 0x01, 0xB7, 0xBD, 0x8A, 0xEB, 0x5E, 0x8E, 0x90, 0x71, 0xB9, 0x1C, 0x22, 0xA3, 0x03, 0x95, 0x31, 0xA3, 0xBC, 0xE0, 0xFF, 0x1D, 0x8D, 0xF5, 0x55, 0x42, 0xAF, 0x9D, 0x2D, 0x14, 0x75, 0x52, 0xE5, 0x77, 0x1C, 0x38, 0x79, 0xE4, 0x40, 0x7B, 0x0E, 0x86, 0xFD, 0x30, 0x12, 0xBD, 0xFA, 0x72, 0x5E, 0x3B, 0xDD, 0x42, 0x33, 0xF8, 0xEA, 0x2A, 0x91, 0x4D, 0x00, 0x06, 0xDC, 0x93, 0xD8, 0x32, 0xDE, 0x11, 0xC7, 0x06, 0x0E, 0xB2, 0xD9, 0xF9, 0x0C, 0xAE, 0x50, 0x26, 0x72, 0xEF, 0x8E, 0xAC, 0x2A, 0x31, 0xBD, 0x3B, 0x35, 0x94, 0x23, 0x0C, 0xAA, 0x92, 0xDB, 0x6D, 0x00, 0x66, 0xFF, 0xA6, 0xC2, 0xA8, 0xE2, 0x0E, 0xF5, 0x6E, 0x26, 0x95, 0xEE, 0x5B, 0xC0, 0x17, 0xD1, 0x8A, 0x4F, 0x00, 0xA6, 0x8F, 0x4C, 0x26, 0x0B, 0xD6, 0x72, 0xE2, 0xC5, 0xB8, 0xDF, 0x4C, 0xBB, 0x70, 0xC6, 0x4A, 0x5E, 0x03, 0x03, 0x2E, 0x50, 0xAB, 0x9E, 0x99, 0x7A, 0x0F, 0x1F, 0xB0, 0xC4, 0x98, 0x32, 0x8E, 0xA6, 0xE7, 0x85, 0x6A, 0x3F, 0xFB, 0xBA, 0x5F, 0x46, 0x77, 0x45, 0xDB, 0xE1, 0x46, 0x0E, 0xA7, 0x85, 0xC6, 0x1B, 0x4B, 0x07, 0xFE, 0x39, 0xE6, 0x61, 0xA5, 0xB8, 0xF6, 0x2C, 0x14, 0x5E, 0x53, 0x4E, 0xFF, 0x7D, 0x06, 0xCC, 0x34, 0x3A, 0x6D, 0x49, 0xDF, 0x0C, 0xB2, 0x05, 0x7D, 0x41, 0x89, 0x7C, 0x02, 0x4A, 0x1F, 0xBC, 0xA4, 0x85, 0x75, 0x53, 0xED, 0x49, 0x8D, 0xEA, 0xCF, 0x19, 0x23, 0xF0, 0xA2, 0xA8, 0x15, 0x5F, 0xAB, 0x0A, 0xC5, 0xCB, 0x2C, 0x78, 0x37, 0x17, 0x0E, 0x08, 0x71, 0xDF, 0x48, 0x95, 0xC1, 0xD0, 0x03, 0x2D, 0xF7, 0x88, 0x1F, 0x0C, 0x5F, 0x2B, 0xD4, 0x93, 0x22, 0x3F, 0x73, 0xBA, 0x21, 0x46, 0x5F, 0xE3, 0x43, 0x44, 0xFF, 0x70, 0x5C, 0x88, 0xF5, 0xA7, 0xCE, 0x9D, 0x99, 0x7E, 0x21, 0xCD, 0x36, 0x5D, 0x21, 0xBB, 0x59, 0xF5, 0xB6, 0xB8, 0xA8, 0x9C, 0x49, 0xEE, 0x7A, 0x8C, 0x68, 0xA9, 0x3F, 0x43, 0xCD, 0xC6, 0x9C, 0xF7, 0xA9, 0xBC, 0x61, 0xEB, 0x32, 0x25, 0x64, 0x8E, 0x5B, 0x4D, 0x90, 0xAB, 0x13, 0x6D, 0x82, 0x59, 0xD3, 0xB0, 0x60, 0x6F, 0xC0, 0xB4, 0x8F, 0x6A, 0xCC, 0x0F, 0xE2, 0x32, 0x32, 0x3F, 0x21, 0xD1, 0x37, 0xE8, 0xC9, 0x06, 0xBE, 0x5F, 0xDC, 0xC7, 0x34, 0x01, 0xC2, 0x23, 0x4C, 0xC4, 0x95, 0x5E, 0xD9, 0xEA, 0x3D, 0x19, 0x06, 0x60, 0x5D, 0xAC, 0x78, 0x8E, 0xFF, 0x8A, 0x86, 0x49, 0xE8, 0xCE, 0x0B, 0x88, 0x7E, 0x58, 0x16, 0x4D, 0xB6, 0xFF, 0x5C, 0x23, 0xA9, 0x51, 0x77, 0xE6, 0x2D, 0x50, 0x4D, 0x6C, 0x15, 0x8A, 0x3F, 0x39, 0xF4, 0x05, 0x87, 0xA3, 0x17, 0xFD, 0xD6, 0x3E, 0x1D, 0xC6, 0x98, 0x22, 0x2C, 0xA1, 0xCF, 0x59, 0x01, 0xB9, 0xF8, 0xBF, 0xE2, 0xE5, 0xB3, 0x73, 0xDD, 0x2E, 0xBC, 0xCC, 0xA7, 0xFD, 0x8C, 0x1D, 0x58, 0xB9, 0xDF, 0x5B, 0x7D, 0xBE, 0xC2, 0x50, 0x09, 0x81, 0x44, 0xDC, 0xC7, 0x59, 0x56, 0x3F, 0xCA, 0x64, 0x67, 0x4D, 0x75, 0xA6, 0x52, 0x4F, 0x6F, 0x7E, 0x8D, 0xAD, 0x58, 0x70, 0x95, 0x3C, 0x6D, 0xD1, 0x1E, 0x0F, 0xD7, 0x36, 0x80, 0xC8, 0x37, 0x90, 0x8F, 0xF0, 0x7A, 0x95, 0xD8, 0x91, 0xC1, 0x51, 0xD8, 0xF4, 0xF5, 0xC8, 0x4C, 0x26, 0xEC, 0xD6, 0x72, 0xD2, 0xE5, 0xB3, 0x90, 0xE3, 0x35, 0xCB, 0xF2, 0x58, 0x55, 0xC2, 0x3B, 0x15, 0xBC, 0x34, 0x48, 0xBD, 0x91, 0x6E, 0xF2, 0x15, 0x28, 0xA4, 0x57, 0xC3, 0x79, 0x5F, 0x98, 0x5A, 0xF1, 0x86, 0x76, 0x85, 0x09, 0x65, 0x04, 0xC8, 0x7B, 0x60, 0xE7, 0x57, 0x4E, 0x04, 0xA6, 0xE0, 0xE5, 0x46, 0x58, 0x8F, 0x47, 0x1E, 0x3B, 0x77, 0xB2, 0xD4, 0x69, 0x00, 0x30, 0x29, 0x8D, 0x67, 0xFD, 0xEA, 0x7C, 0x52, 0xCE, 0x2F, 0xEC, 0x54, 0xAE, 0xFB, 0x4F, 0xFB, 0x59, 0x81, 0xAB, 0x44, 0xCC, 0xD1, 0x96, 0xC2, 0xE0, 0x19, 0x20, 0x53, 0xFC, 0x6A, 0x01, 0xEB, 0x37, 0x2E, 0x61, 0xFB, 0xA5, 0xEA, 0xE2, 0x6A, 0x4F, 0x2E, 0x32, 0xD2, 0x95, 0xDA, 0xDF, 0x18, 0x9F, 0xED, 0xD1, 0x4A, 0x1F, 0x03, 0xC5, 0x68, 0xB3, 0xD1, 0x2C, 0x09, 0xE9, 0x27, };
    // 输入数据长度
    uint32_t buf_length = sizeof(inputdata);

    // SM2私钥
    uint8_t Private_Key[32] = {0xBF, 0x72, 0x24, 0x72, 0x6B, 0xCF, 0x10, 0x2D, 0xF8, 0x55, 0x91, 0x52, 0x46, 0xB1, 0x13, 0x65, 0x5B, 0x39, 0x76, 0xF4, 0xD2, 0xA4, 0xD8, 0x49, 0x7A, 0x14, 0xAD, 0xD5, 0x0D, 0x82, 0xF2, 0x9C, };

    // SM2公钥
    uint8_t Publickey[64] = {0x50, 0xE2, 0x78, 0xAB, 0xBA, 0xB4, 0x5C, 0xA2, 0xE8, 0x13, 0x41, 0x99, 0xE0, 0xED, 0xE0, 0xCA, 0xA6, 0x94, 0xD3, 0xDE, 0x26, 0xC9, 0xFC, 0xEF, 0xFC, 0xDF, 0xEE, 0xDC, 0x85, 0x92, 0xCC, 0x9D, 0x4E, 0x6E, 0xDE, 0x36, 0x2A, 0x2C, 0x62, 0x47, 0xA1, 0x56, 0x33, 0x63, 0x84, 0xDC, 0x9C, 0x09, 0xE3, 0x6B, 0x14, 0xB5, 0x63, 0x9B, 0xEB, 0xDD, 0x1B, 0x99, 0xC9, 0x2A, 0x4E, 0x46, 0x44, 0xCD, };

    // 签名结果缓冲区
    uint8_t Sig_Result[72];
    uint32_t siglen;

    // 调用SM2签名函数
    ret = sm2sign_main(inputdata, buf_length, Private_Key, Publickey, &Sig_Result[0], &siglen);
 
    printf("ret = %d\n",ret);

    // 打印签名结果
    printf("Sig_Result\n");
    printf("\n");
    for (uint32_t i = 0; i < siglen; i++)
    {
        printf("%02x ", Sig_Result[i]);
    }
    printf("\n");

    // 打印公钥
    printf("Publickey\n");
    for (uint32_t i = 0; i < 64; i++)
    {
        printf("%02x ", Publickey[i]);
    }
    printf("\n");

    // 打印输入数据
    printf("inputdata\n");
    for (uint32_t i = 0; i < buf_length; i++)
    {
        printf("%02x ", inputdata[i]);
    }
    printf("\n");

    // 打印用户ID
    printf("USERID\n");
    for (uint32_t i = 0; i < SM2_DEFAULT_ID_LENGTH; i++)
    {
        printf("%02x ", sm2_userid[i]);
    }
    printf("\n");

    // 验证签名
    ret = sm2verify_main(inputdata, buf_length, Private_Key, Publickey, Sig_Result, siglen);
    printf("ret = %d",ret);

    // 修改签名后再次验证(用于测试验证失败情况)
    Sig_Result[20] += 1;
    ret = sm2verify_main(inputdata, buf_length, Private_Key, Publickey, Sig_Result, siglen);
    printf("ret = %d",ret);
}
